package me.yricky.alia.ui.layoutPage.renderModel

import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
import me.yricky.alia.data.hierarchy.Cell
import me.yricky.alia.data.hierarchy.Layer
import me.yricky.alia.data.shape.Box
import me.yricky.alia.data.shape.Shape
import me.yricky.alia.data.shape.Text
import me.yricky.alia.ui.layoutPage.internalBrushes
import me.yricky.alia.ui.layoutPage.solidBrush
import me.yricky.alia.ui.toOffset
import me.yricky.alia.utils.filterInstanceAnd
import kotlin.math.abs

/**
 * @author Yricky
 * @date 2022/2/11
 */
class LayerRender(
    var layerId: Layer.LDPair,
    var style:LayerStyle,

    val renderUnits:MutableList<Pair<Cell,LayerRenderUnit>>,
){
    /**
     * 存放一个Cell中一个Layer渲染所需数据的类
     */
    data class LayerRenderUnit(
        val cell: Cell,
        val texts:List<Text>,
        val shapes:List<Shape>,
        val matrix:Matrix,
    ){
        val shapePaths: List<Pair<Box, Path>> = shapes.map { sh ->
            val li = sh.vertices.map {
                it.toOffset()
            }
            val p = Path()
            if(li.isNotEmpty()){
                var lastDot = li.first()
                li.also {
                    p.moveTo(lastDot.x,-lastDot.y)
                }.forEach {
                    if(abs(it.x - lastDot.x)>2 || abs(it.y - lastDot.y) > 2){
                        p.lineTo(it.x,-it.y)
                        lastDot = it
                    }
                }
            }
            Pair(sh.bBox,p)
        }
    }



    class LayerStyle(
        val color: Color = Color.Black,
        val brush: ShaderBrush = solidBrush,
        val stroke:Boolean = true,
        val strokeWidth :Float = 1.0f,
        val aa:Boolean = false,
    ){
        fun strokePaint(): Paint = mStrokePaint
        fun fillPaint(size: Size): Paint {
            if(mSize != size){
                mSize = size
                return Paint().also {
                    it.isAntiAlias = aa
                    it.shader = brush.createShader(size)
                    it.colorFilter  = ColorFilter.tint(color)
                    mFillPaint = it
                }
            }else{
                return mFillPaint ?: Paint().also {
                    it.isAntiAlias = aa
                    it.shader = brush.createShader(size)
                    it.colorFilter  = ColorFilter.tint(color)
                    mFillPaint = it
                }
            }
        }
        private val mStrokePaint by lazy{
            Paint().also {
                it.isAntiAlias = aa
                it.colorFilter  = ColorFilter.tint(color)
                it.style = PaintingStyle.Stroke
                it.strokeWidth = strokeWidth
            }
        }
        private var mSize: Size? = null
        private var mFillPaint: Paint? = null

        companion object{
            @OptIn(ExperimentalGraphicsApi::class)
            fun get(layer: Layer.LDPair):LayerStyle= LayerStyle(
                color = Color.hsv((layer.layerId*20 % 360).toFloat(),0.8f,0.8f,0.4f),
                brush = internalBrushes.values.toList()[layer.layerId%internalBrushes.size]
            )
        }
    }
}